%option noyywrap
%{
/*****************声明和选项设置  begin*****************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "parse_tree.h"
#include "syntax_analyzer.h"

int lines=1;
int pos_start=1;
int pos_end=1;
char token_name[20];

void new_node(char *text){
    yylval.node = new_parse_tree_node(text);
}
/*****************声明和选项设置  end*****************/
%}


/*整形常量*/
dig [0-9]
hex_dig [0-9a-fA-F]
oct_dig [0-7]
non_dig [1-9]
hex_pre 0[xX]
hex_con {hex_pre}{hex_dig}{hex_dig}*
oct_con 0{oct_dig}*
dec_con {non_dig}{dig}*
int_con ({dec_con}|{oct_con}|{hex_con})

/*浮点型常量*/
hex_dig_seq {hex_dig}+
sign ("+"|"-")
dig_seq {dig}+
bin_exp_par [pP]{sign}?{dig_seq}
hex_fra_con ({hex_dig_seq}?"."{hex_dig_seq}|{hex_dig_seq}".")

exp_par [eE]{sign}?{dig_seq}
fra_con ({dig_seq}?"."{dig_seq}|{dig_seq}".")
hex_flo_con ({hex_pre}{hex_fra_con}{bin_exp_par}|{hex_pre}{hex_dig_seq}{bin_exp_par})
dec_flo_con ({fra_con}{exp_par}?|{dig_seq}{exp_par})
flo_con ({dec_flo_con}|{hex_flo_con})


%%

[ \t]      {pos_start = pos_end; pos_end += yyleng;}
\n         {pos_start = 1; pos_end = 1; lines += 1;}

"//"[^\n]+  {pos_start = pos_end; pos_end += yyleng;}
"/*"([^*]|\*+[^*/])*\*+"/"  {
    pos_start = pos_end;
    pos_end += yyleng;
    for(int i=0; i<yyleng; i++)
    {
        if(yytext[i] == '\n')
            lines++;
    }
}

"int"             {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "INT"); new_node(yytext); return INT;}
"float"           {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "FLOAT"); new_node(yytext); return FLOAT;}
"void"            {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "VOID"); new_node(yytext); return VOID;}
"const"           {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "CONST"); new_node(yytext); return CONST;}
"return"          {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "RETURN"); new_node(yytext); return RETURN;}
"if"              {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "IF"); new_node(yytext); return IF;}
"else"            {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "ELSE"); new_node(yytext); return ELSE;}
"while"           {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "WHILE"); new_node(yytext); return WHILE;}
"break"           {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "BREAK"); new_node(yytext); return BREAK;}
"continue"        {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "CONTINUE"); new_node(yytext); return CONTINUE;}

{int_con}                 {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "INTCONST"); new_node(yytext); return INTCONST;}
{flo_con}                 {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "FLOATCONST"); new_node(yytext); return FLOATCONST;}
[a-zA-Z_][a-zA-Z0-9_]*    {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "IDENT"); new_node(yytext); return IDENT;}

";"               {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "SEMICOLON"); new_node(yytext); return SEMICOLON;}
","               {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "COMMA"); new_node(yytext); return COMMA;}
"="               {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "ASSIGN"); new_node(yytext); return ASSIGN;}

"<"               {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "LT"); new_node(yytext); return LT;}
"<="              {pos_start = pos_end; pos_end += 2; strcpy(token_name, "LET"); new_node(yytext); return LET;}
">"               {pos_start = pos_end; pos_end += yyleng; strcpy(token_name, "GT"); new_node(yytext); return GT;}
">="              {pos_start = pos_end; pos_end += 2; strcpy(token_name, "GET"); new_node(yytext); return GET;}
"=="              {pos_start = pos_end; pos_end += 2; strcpy(token_name, "EQ"); new_node(yytext); return EQ;}
"!="              {pos_start = pos_end; pos_end += 2; strcpy(token_name, "NEQ"); new_node(yytext); return NEQ;}

"\+"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "ADD"); new_node(yytext); return ADD;}
"-"               {pos_start = pos_end; pos_end += 1; strcpy(token_name, "SUB"); new_node(yytext); return SUB;}
"\*"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "MUL"); new_node(yytext); return MUL;}
"\/"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "DIV"); new_node(yytext); return DIV;}
"%"               {pos_start = pos_end; pos_end += 1; strcpy(token_name, "MOD"); new_node(yytext); return MOD;}

"&&"              {pos_start = pos_end; pos_end += 2; strcpy(token_name, "AND"); new_node(yytext); return AND;}
"\|\|"            {pos_start = pos_end; pos_end += 2; strcpy(token_name, "OR"); new_node(yytext); return OR;}
"!"               {pos_start = pos_end; pos_end += 1; strcpy(token_name, "NOT"); new_node(yytext); return NOT;}

"\("              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "LPARENTHESIS"); new_node(yytext); return LPARENTHESIS;}
"\)"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "RPARENTHESIS"); new_node(yytext); return RPARENTHESIS;}
"\["              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "LBRACKET"); new_node(yytext); return LBRACKET;}
"\]"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "RBRACKET"); new_node(yytext); return RBRACKET;}
"\{"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "LBRACE"); new_node(yytext); return LBRACE;}
"\}"              {pos_start = pos_end; pos_end += 1; strcpy(token_name, "RBRACE"); new_node(yytext); return RBRACE;}
.                 {printf("Error: Invalid character '%s' at line %d\n", yytext, lines); pos_end++;}

%%
